Skip to content

fix(runner): Stream End fixes - #1920

Open
Mazi02 wants to merge 3 commits into
devfrom
fix/runner-end-stream-fixes
Open

fix(runner): Stream End fixes#1920
Mazi02 wants to merge 3 commits into
devfrom
fix/runner-end-stream-fixes

Conversation

@Mazi02

@Mazi02 Mazi02 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Motivation and Context

Follow-up to the end-stream feature. The runner could be killed by a data race, ending an
already ended stream returned a 500, the discard logic depended on behaviour that contradicts
its own documentation, and discarded recordings were never deleted from disk.

Description

  • jobs and discard were used from the gRPC handlers, the job goroutines and the heartbeat
    without synchronization. Go aborts the whole process for this, taking every running job with
    it. Both are now behind a RWMutex, accessed via jobCount/discarded/endJob.
  • endRunnerJob treats codes.NotFound as success. The runner only knows the jobs of its
    current process while the job rows live in the db, so an unknown job is already in the
    desired state (finished regularly, double click, runner restarted).
  • The VoD actions are passed to RunAction as their own list and skipped explicitly, instead
    of detecting StreamEnd by comparing function pointers. The Action doc comment now
    describes what actually happens: an AbortingError stops the retries, not the following
    actions — ending a stream early depends on that.
  • New DiscardRecording action writes the .del- marker that livestreamCleanup looks for.
    It was previously written by CheckVoD only, which discard skips, so discarded recordings
    stayed on disk forever.
  • RequestStreamEnd returns an actual response message; (nil, nil) is an internal error in gRPC.

Steps for Testing

Prerequisites:

  • 1 Lecturer
  • 1 Livestream
  • 1 Runner
  1. Log in as the lecturer and start a livestream.
  2. Open /api/stream/<streamID>/end → the stream stops being live in the UI.
  3. Open the same URL again → 200, not a 500. Same after restarting the runner.
  4. Start a second livestream and open /api/stream/<streamID>/end?discard=true → the runner
    logs discarding recording, skipping VoD creation, no VoD is created, and the recording
    directory under SEGMENT_PATH is deleted within a minute.

Mazi02 and others added 3 commits August 14, 2026 00:00
Writes the .del- marker livestreamCleanup looks for. So far that marker was only
written by CheckVoD, which the discard path skips.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The skip detected StreamEnd by comparing function pointers and depended on the
loop position, so reordering the action list broke it silently. RunAction now
takes the VoD and discard actions as their own lists.

It also depended on AbortingError not skipping the following actions, contrary
to the doc comment on Action - describe the actual behaviour instead, ending a
stream early needs StreamEnd to run after the cancelled Stream action.

RequestStreamEnd returns an actual response now, (nil, nil) is an internal error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The runner only tracks jobs of its current process while the job rows live in
the db, so NotFound is the normal case after a regular run, a double click on
"end stream" or a runner restart - and turned every such click into a HTTP 500.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant